﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lextm.SharpSnmpLib;
using Lextm.SharpSnmpLib.Messaging;
using System.Net;
using System.Net.Sockets;
using Domain.NetworkService.Behaviors.Interfaces;

namespace Domain.NetworkService
{
    public class SnmpTestBehavior : INetworkServiceTest
    {
        IPAddress ip;
        string community;
        public string snmpOID { get; private set; }
        public SnmpTestBehavior(IPAddress ip, TimeSpan timeout, string snmpOID, string community = "")
        {
            Domain.Entities.SecureStringManager ssm = new Domain.Entities.SecureStringManager();

            this.ip = ip;
            this.community = community.Equals("") ? ssm.Unprotect(System.Configuration.ConfigurationManager.AppSettings["community"]) : community;
            this.snmpOID = snmpOID;
            this.Timeout = timeout;
            this.Description = new Description()
          {
              networkTestDescription = NetworkTestDescription.SNMP,
              Special = SnmpOid.TranslateOidToName(snmpOID), 
              Timeout = timeout,
              HostNameOrIP = ip.ToString()
          };
        }
        public SnmpTestBehavior(IPAddress ip, TimeSpan timeout, OidNames oidName, string community = "")
        {
            Domain.Entities.SecureStringManager ssm = new Domain.Entities.SecureStringManager();
            this.ip = ip;
            this.community = community.Equals("") ? ssm.Unprotect(System.Configuration.ConfigurationManager.AppSettings["community"]) : community;
            this.snmpOID = SnmpOid.TranslateNameToOid(oidName).ToString();
            this.Timeout = timeout;
            this.Description = new Description()
            {
                networkTestDescription = NetworkTestDescription.SNMP,
                Special = SnmpOid.TranslateOidToName(snmpOID),
                Timeout = timeout,
                HostNameOrIP = ip.ToString()
            };
        }

        public NetworkTestResult Start()
        {
            var result = new List<Variable>();
            try
            {
                Messenger.Walk(VersionCode.V1,
                                   new IPEndPoint(ip, 161),
                                   new OctetString(community),
                                   new ObjectIdentifier(snmpOID),
                                   result,
                                   500,
                                   WalkMode.WithinSubtree);
            }
            catch (SnmpException snmpEx)
            {
                return FailedResult(snmpEx.Message);
            }
            catch (SocketException socketEx)
            {
                string msg = "SocketError";
                foreach (SocketError sError in Enum.GetValues(typeof(SocketError)))
                {
                    if (socketEx.SocketErrorCode == sError)
                    {
                        msg = sError.ToString();
                    }
                }
                return FailedResult(msg);
            }
            if (result.Count > 0)
            {
                return new SnmpResult()
                {
                    IP = ip,
                    Status = ResultStatus.Success,
                    VarDateTime = DateTime.Now,
                    Variable = SnmpOid.TranslateOidToName(snmpOID),
                    Data = produceResult(result)
                };
            }
            else
            {
                return FailedResult("Пустая строка");
            }
        }
        private SnmpResult FailedResult(string msg)
        {
            if (msg.Contains("Lextm.SharpSnmpLib.Messaging.TimeoutException"))
            {
                msg = "TimedOut";
            }

            return new SnmpResult()
            {
                IP = ip,
                Status = ResultStatus.Failed,
                VarDateTime = DateTime.Now,
                Variable = SnmpOid.TranslateOidToName(snmpOID),
                Data = msg
            };
        }
        private string produceResult(List<Variable> result)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in result)
            {
                sb.AppendFormat("{0}; ", item.Data);
            }
            return sb.ToString();
        }

        public IDescription Description { get; set; }
        public TimeSpan Timeout { get; set; }
    }
}
